﻿using System.Collections.Generic;
using UnityEngine;

//模拟移动点结构
struct AutoMovePos
{
    public int nPosSerial;                               //当前点序列号
    public float fDstPosX;                               //当前点目的地X
    public float fDstPosZ;                               //当前点目的地Z
}

public class AutoMove : MonoBehaviour
{
    List<AutoMovePos> posList = new List<AutoMovePos>();    //移动路径列表
    private int nCurPosSerial;                              //当前移动的路径序列
    private bool bIsMove;                                   //是否正在移动
    
    public void ResetAutoMove()
    {
        posList.Clear();
        nCurPosSerial = 0;
        bIsMove = false;
    }

    private bool IsReachPoint(AutoMovePos pos)
    {
        //先判断序列号
        if (pos.nPosSerial != nCurPosSerial) { return false; }
        Vector2 dstPos = new Vector2(pos.fDstPosX, pos.fDstPosZ);
        Vector2 curPos = new Vector2(transform.position.x, transform.position.z);
        return Vector2.Distance(curPos, dstPos) < 0.5f;
    }

    //到达当前点，删除当前点，向下一个点移动
    private void ReachPoint()
    {
        if (posList.Count <= 0)
        {
            return;
        }
        //移除当前点
        posList.RemoveAt(0);
        
        if (posList.Count <= 0)
        {
            //已经无点，停止移动
            StopMove();
        }
        else
        {
            BeginMove(posList[0]);
        }
    }

    //移动开始
    private void BeginMove(AutoMovePos dstPos)
    {
        //记录当前点序列号
        nCurPosSerial = dstPos.nPosSerial;
        //开始移动
        Vector3 dest = new Vector3(dstPos.fDstPosX, 0.0f, dstPos.fDstPosZ);
        bIsMove = true;
    }

    //移动结束
    private void StopMove()
    {
        ResetAutoMove();
    }

    //强制打断移动
    //策略是找到路径中和GC_STOP的Serial相同点，走完之前点，删除之后点，并且将该点的目的地变为GC_STOP中的坐标
    public void InterruptMove()
    {
        for (int i = 0; i < posList.Count; ++i)
        {
                //如果不是最后一个点，则清除该点之后所有点
                if (i < posList.Count - 1)
                {
                    posList.RemoveRange(i + 1, posList.Count - i - 1);
                }

                //修改i数值
                AutoMovePos autoPos = posList[i];

                //删除原有数据，插入新数值
                posList.RemoveAt(i);
                posList.Add(autoPos);

                //如果是第一个点，则重新发起移动
                if (i == 0)
                {
                    BeginMove(posList[i]);
                }

                return;
        }

        //如果没找到点，也强制打断移动
        StopMove();
    }

    //卡点检测
    const float m_fObstacleTestInterval = 1.0f;
    float fObstacleTestTime;
    void ObstacleTest()
    {
        if (!bIsMove)
        {
            return;
        }
        if (Time.time - fObstacleTestTime > m_fObstacleTestInterval)
        {
            fObstacleTestTime = Time.time;
        }
        else
        {
            return;
        }

        //长时间卡在一个点，则直接SetPos过去，并且删除当前点
        {
            Vector3 pos = new Vector3(posList[0].fDstPosX, 0, posList[0].fDstPosZ);
            transform.position = pos; ReachPoint();
        }
    }

    void FixedUpdate()
    {
        //如果posList未初始化（可能是主角）或者无自动移动行为，返回
        if (posList.Count <= 0)
        {
            return;
        }

        //防卡机检测
        ObstacleTest();

        //由于防卡机检测中可能将m_postList置空，所以这里要再次检测
        if (posList.Count <= 0)
        {
            return;
        }

        if (bIsMove)
        {
            //如果正在移动中,判断是否到达
            if (IsReachPoint(posList[0]))
            {
                ReachPoint();
                return;
            }
            else
            {
                BeginMove(posList[0]);
            }
        }
        else
        {
            //如果未移动但是posList不为空
            BeginMove(posList[0]);
        }
    }
}